<!DOCTYPE html>
<html>
<!--
Copyright 2010 The Closure Library Authors. All Rights Reserved.

Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>Closure Unit Tests - goog.ui.Textarea</title>
  <script src="../base.js"></script>
  <script>
    goog.require('goog.debug.DivConsole');
    goog.require('goog.debug.LogManager');
    goog.require('goog.dom');
    goog.require('goog.dom.classlist');
    goog.require('goog.events');
    goog.require('goog.log');
    goog.require('goog.object');
    goog.require('goog.style');
    goog.require('goog.testing.ExpectedFailures');
    goog.require('goog.testing.events');
    goog.require('goog.testing.events.EventObserver');
    goog.require('goog.testing.jsunit');
    goog.require('goog.ui.Control');
    goog.require('goog.ui.ControlRenderer');
    goog.require('goog.ui.Textarea');
    goog.require('goog.ui.TextareaRenderer');
    goog.require('goog.userAgent');
    goog.require('goog.userAgent.product');
    goog.require('goog.userAgent.product.isVersion');
  </script>
  <style>
    textarea {
      /* Some of the height tests are based on font size px values. */
      font-size: 1em;
      height: 25px; /* Need to force an initial height < our minHeight. */
      width: 150px;
      padding: 2px;
      margin: 0;
      border: 1px solid #000;
    }
    .drop-shadowed {
      filter:progid:DXImageTransform.Microsoft.DropShadow(color='#e7e7e7',
          offX='5',offY='5');
      box-shadow: 5px 5px 0 #e7e7e7;
      -moz-box-shadow: 5px 5px 0 #e7e7e7;
      -webkit-box-shadow: 5px 5px 0 #e7e7e7;
    }
  </style>
</head>
<body>
  <h1>goog.ui.Textarea tests</h1>
  <p>Here's a textarea defined in markup:</p>
  <textarea id="demo-textarea">Foo</textarea>
  <div id="sandbox"></div>
  <script>
    var sandbox = goog.dom.getElement('sandbox');
    var textarea;
    var demoTextareaElement = goog.dom.getElement('demo-textarea');
    var expectedFailures = new goog.testing.ExpectedFailures();

    function setUp() {
      textarea = new goog.ui.Textarea();
    }

    function tearDown() {
      expectedFailures.handleTearDown();
      textarea.dispose();
      goog.dom.removeChildren(sandbox);
    }

    /**
     * @return {boolean} Whether we're on Mac Safari 3.x.
     */
    function isMacSafari3() {
      return goog.userAgent.WEBKIT && goog.userAgent.MAC &&
          !goog.userAgent.isVersionOrHigher('527');
    }

    /**
     * @return {boolean} Whether we're on Linux Firefox 3.6.3.
     */
    function isLinuxFirefox() {
      return goog.userAgent.product.FIREFOX && goog.userAgent.LINUX;
    }

    /**
     * @return {boolean} Whether we're on Firefox 3.0.
     */
    function isFirefox3() {
      return goog.userAgent.GECKO &&
          !goog.userAgent.isVersionOrHigher('1.9.1');
    }

    function testConstructor() {
      assertNotNull('Textarea must not be null', textarea);
      assertEquals('Renderer must default to expected value',
          goog.ui.TextareaRenderer.getInstance(), textarea.getRenderer());

      var fakeDomHelper = {
        'getDocument': function() { return true; }
      };
      var testTextarea = new goog.ui.Textarea('Hello',
          goog.ui.TextareaRenderer.getInstance(), fakeDomHelper);
      assertEquals('Content must have expected content', 'Hello',
          testTextarea.getContent());
      assertEquals('Renderer must have expected value',
          goog.ui.TextareaRenderer.getInstance(), testTextarea.getRenderer());
      assertEquals('DOM helper must have expected value', fakeDomHelper,
          testTextarea.getDomHelper());
      testTextarea.dispose();
    }

    function testConstructorWithDecorator() {
      var decoratedTextarea = new goog.ui.Textarea();
      decoratedTextarea.decorate(demoTextareaElement);
      assertEquals('Textarea should have current content after decoration',
          'Foo', decoratedTextarea.getContent());
      var initialHeight = decoratedTextarea.getHeight_();
      var initialOffsetHeight = decoratedTextarea.getElement().offsetHeight;
      // focus() will trigger the grow/shrink flow.
      decoratedTextarea.getElement().focus();
      assertEquals('Height should not have changed without content change',
           initialHeight, decoratedTextarea.getHeight_());
      assertEquals('offsetHeight should not have changed without content ' +
          'change', initialOffsetHeight,
          decoratedTextarea.getElement().offsetHeight);
      decoratedTextarea.dispose();
    }

    function testGetSetContent() {
      textarea.render(sandbox);
      assertEquals('Textarea\'s content must default to an empty string',
          '', textarea.getContent());
      textarea.setContent(17);
      assertEquals('Textarea element must have expected content', '17',
          textarea.getElement().value);
      textarea.setContent('foo');
      assertEquals('Textarea element must have updated content', 'foo',
          textarea.getElement().value);
    }

    function testGetSetValue() {
      textarea.render(sandbox);
      assertEquals('Textarea\'s content must default to an empty string',
          '', textarea.getValue());
      textarea.setValue(17);
      assertEquals('Textarea element must have expected content', '17',
          textarea.getValue());
      textarea.setValue('17');
      assertEquals('Textarea element must have expected content', '17',
          textarea.getValue());
    }

    function testBasicTextareaBehavior() {
      var observer = new goog.testing.events.EventObserver();
      goog.events.listen(textarea, goog.ui.Textarea.EventType.RESIZE, observer);
      textarea.render(sandbox);
      var el = textarea.getElement();
      var heightBefore = textarea.getHeight_();
      assertTrue('One resize event should be fired during render',
          observer.getEvents().length == 1);
      textarea.setContent('Lorem ipsum dolor sit amet, consectetuer ' +
          'elit. Aenean sollicitudin ultrices urna. Proin vehicula mauris ac ' +
          'est. Ut scelerisque, risus ut facilisis dictum, est massa lacinia ' +
          'lorem, in fermentum purus ligula quis nunc.');
      var heightAfter = textarea.getHeight_();
      assertTrue('With this much content, height should have grown.',
          heightAfter > heightBefore);
      assertTrue('With a height change, a resize event should have fired.',
          observer.getEvents().length == 2);
      textarea.setContent('');
      heightAfter = textarea.getHeight_();
      assertTrue('Textarea should shrink with no content.',
          heightAfter <= heightBefore);
      assertTrue('With a height change, a resize event should have fired.',
          observer.getEvents().length == 3);
      goog.events.unlisten(textarea, goog.ui.Textarea.EventType.RESIZE,
          observer);
    }

    function testMinHeight() {
      textarea.render(sandbox);
      textarea.setMinHeight(50);
      assertEquals('offsetHeight should be 50 initially', 50,
          textarea.getElement().offsetHeight);
      textarea.setContent('Lorem ipsum dolor sit amet, consectetuer  ' +
          'elit. Aenean sollicitudin ultrices urna. Proin vehicula mauris ac ' +
          'est. Ut scelerisque, risus ut facilisis dictum, est massa lacinia ' +
          'lorem, in fermentum purus ligula quis nunc.');
      assertTrue('getHeight_() should be > 50',
          textarea.getHeight_() > 50);

      textarea.setContent('');
      assertEquals('With no content, offsetHeight should go back to 50, ' +
          'the minHeight.', 50, textarea.getElement().offsetHeight);

      expectedFailures.expectFailureFor(isMacSafari3());
      try {
        textarea.setMinHeight(0);
        assertTrue('After setting minHeight to 0, offsetHeight should ' +
            'now be < 50, but it is ' + textarea.getElement().offsetHeight,
            textarea.getElement().offsetHeight < 50);
      } catch (e) {
        expectedFailures.handleException(e);
      }
    }

    function testMouseUpListener() {
      textarea.render(sandbox);
      textarea.setMinHeight(100);
      textarea.setMaxHeight(200);
      textarea.mouseUpListener_({});
      assertEquals('After a mouseup which is not a resize, minHeight should ' +
          'still be 100', 100, textarea.minHeight_);

      // We need to test how CSS drop shadows effect this too.
      goog.dom.classlist.add(textarea.getElement(), 'drop-shadowed');
      textarea.mouseUpListener_({});
      assertEquals('After a mouseup which is not a resize, minHeight should ' +
          'still be 100 even with a shadow', 100, textarea.minHeight_);

    }

    function testMaxHeight() {
      textarea.render(sandbox);
      textarea.setMaxHeight(50);
      assertTrue('Initial offsetHeight should be less than 50',
          textarea.getElement().offsetHeight < 50);
      var newContent = 'Lorem ipsum dolor sit amet, consectetuer adipiscing ' +
          'elit. Aenean sollicitudin ultrices urna. Proin vehicula mauris ac ' +
          'est. Ut scelerisque, risus ut facilisis dictum, est massa lacinia ' +
          'lorem, in fermentum purus ligula quis nunc.'
      textarea.setContent(newContent);

      assertTrue('With lots of content, getHeight_() should be > 50',
          textarea.getHeight_() > 50);
      assertEquals('Even with lots of content, offsetHeight should be 50 ' +
          'with maxHeight set', 50, textarea.getElement().offsetHeight);
      textarea.setMaxHeight(0);
      assertTrue('After setting maxHeight to 0, offsetHeight should now ' +
          'be > 50', textarea.getElement().offsetHeight > 50);
    }

    function testMaxHeight_canShrink() {
      textarea.render(sandbox);
      textarea.setMaxHeight(50);
      assertTrue('Initial offsetHeight should be less than 50',
          textarea.getElement().offsetHeight < 50);
      var newContent = 'Lorem ipsum dolor sit amet, consectetuer adipiscing ' +
          'elit. Aenean sollicitudin ultrices urna. Proin vehicula mauris ac ' +
          'est. Ut scelerisque, risus ut facilisis dictum, est massa lacinia ' +
          'lorem, in fermentum purus ligula quis nunc.'
      textarea.setContent(newContent);

      assertEquals('Even with lots of content, offsetHeight should be 50 ' +
          'with maxHeight set', 50, textarea.getElement().offsetHeight);
      textarea.setContent('');
      assertTrue('With no content, offsetHeight should be back to < 50',
          textarea.getElement().offsetHeight < 50);
    }

    function testSetPlaceholder() {
      textarea.setPlaceholder('Some default text here.');
      textarea.setPlaceholder('new default text...');
      textarea.render(sandbox);
      if (textarea.supportsNativePlaceholder_()) {
        assertEquals('new default text...', textarea.getElement().placeholder);
      }
      assertEquals('', textarea.getValue());
      textarea.setValue('some value');
      assertEquals('some value', textarea.getValue());
      // ensure setting a new placeholder doesn't replace the value.
      textarea.setPlaceholder('some new placeholder');
      assertEquals('some value', textarea.getValue());
    }

    function testSetPlaceholderForInitialContent() {
      var testTextarea = new goog.ui.Textarea('initial content');
      testTextarea.render(sandbox);
      assertEquals('initial content', testTextarea.getValue());
      testTextarea.setPlaceholder('new default text...');
      assertEquals('initial content', testTextarea.getValue());
      testTextarea.setValue('new content');
      assertEquals('new content', testTextarea.getValue());
      testTextarea.setValue('');
      assertEquals('', testTextarea.getValue());
      if (!testTextarea.supportsNativePlaceholder_()) {
        // Pretend we leave the textarea. When that happens, the
        // placeholder text should appear.
        assertEquals('', testTextarea.getElement().value);
        testTextarea.blur_();
        assertEquals('new default text...', testTextarea.getElement().value);
      }
    }

    function testMinAndMaxHeight() {
      textarea.render(sandbox);
      textarea.setMinHeight(50);
      textarea.setMaxHeight(150);
      assertEquals('offsetHeight should be 50 initially', 50,
          textarea.getElement().offsetHeight);

      textarea.setContent('Lorem ipsum dolor sit amet, consectetuer  ' +
          'elit. Aenean sollicitudin ultrices urna. Proin vehicula mauris ac ' +
          'est. Ut scelerisque, risus ut facilisis dictum, est massa lacinia ' +
          'lorem, in fermentum purus ligula quis nunc.');

      var height = textarea.getHeight_();
      // For some reason Mac Safari 3 has 136 and Linux FF has 146 here.
      expectedFailures.expectFailureFor(isMacSafari3() || isLinuxFirefox());
      try {
        assertTrue('With lots of content, getHeight_() should be > 150 ' +
          '(it is ' + height + ')', height > 150);
        assertEquals('Even with lots of content, offsetHeight should be 150 ' +
            'with maxHeight set', 150,
            textarea.getElement().offsetHeight);

        textarea.setMaxHeight(0);
        assertTrue('After setting maxHeight to 0, offsetHeight should now ' +
            'be > 150 (it is ' + textarea.getElement().offsetHeight + ')',
            textarea.getElement().offsetHeight > 150);

        textarea.setContent('');
        textarea.setMinHeight(0);
        assertTrue('After setting minHeight to 0, with no contents, ' +
            'offsetHeight should now be < 50',
            textarea.getElement().offsetHeight < 50);
      } catch (e) {
        expectedFailures.handleException(e);
      }
    }

    function testSetValueWhenInvisible() {
      textarea.render(sandbox);
      var content = 'Lorem ipsum dolor sit amet, consectetuer  ' +
          'elit. Aenean sollicitudin ultrices urna. Proin vehicula mauris ac ' +
          'est. Ut scelerisque, risus ut facilisis dictum, est massa lacinia ' +
          'lorem, in fermentum purus ligula quis nunc.';
      textarea.setValue(content);
      var height = textarea.getHeight_();
      var elementHeight = goog.style.getStyle(textarea.getElement(), 'height');
      assertEquals(height + 'px', elementHeight);

      // Hide the element, height_ should be invalidate when setValue().
      goog.style.setElementShown(textarea.getElement(), false);
      textarea.setValue(content);

      // Show the element again.
      goog.style.setElementShown(textarea.getElement(), true);
      textarea.setValue(content);
      height = textarea.getHeight_();
      elementHeight = goog.style.getStyle(textarea.getElement(), 'height');
      assertEquals(height + 'px', elementHeight);
    }

  </script>
</body>
</html>
